# ☕ Coffee API

Flask + SQLAlchemy + PostfreSQL + Docker.

Интересные моменты:

- Настройка PostgreSQL при помощи кастомного конфига (изменены настройки логов).
- В таблицах используются типы `ARRAY(String)`, `JSONB`.
- Генерация тестовых данных (адреса, кофе) при помощи внешнего сервиса: [RandomDataAPI](https://random-data-api.com).
- Запросы к БД по значению отдельных ключей поля `JSONB`.
- Полнотекстовый поиск по значениям отдельного поля (название кофе).

## Запуск проекта

```bash
docker compose up -d --build
```

API Flask будет доступно на порту 8000, а на 80 порту будет pgAdmin 4.

Первый запрос Flask займет ±2 секунды из-за таймаута в обращении к внешнему API для генерации тестовых 
данных.

## Notes

Подключиться к БД: `psql -d skillbox_db -U admin`.

Посмотреть структуру таблицы в `psql` можно командой `\d coffee`.

Для фильтрации по значению ключей поля типа JSON, используем для поля тип `from sqlalchemy.dialects.postgresql import JSONB`
и тип поля ставим `address: Mapped[dict] = mapped_column(JSONB, nullable=True)`. При создании записей, сохраняем 
туда объекты типа `dict`.

Пример SQL запроса с фильтром по полю типа JSONB:

```sql
SELECT * FROM users
WHERE CAST((users.address ->> 'country') AS VARCHAR) = 'Italy';
```

Пример запроса с использованием ORM SQLAlchemy:

```python
session.query(User)
        .filter(User.address["country"].as_string() == country)
        .all()
```

Выборка уникальных значений из всех полей `notes` типа `ARRAY`:

```sql
SELECT DISTINCT unnest(notes) AS unique_notes FROM coffee;
```

То же самое с использованием ORM SQLAlchemy:

```python
# result will be an array of single-element tuples:
result = session.query(distinct(func.unnest(Coffee.notes).label("value"))).all()
notes = [elem[0] for elem in result]
```

Запрашиваем элементы поля JSONB при помощи чистого SQL:

```sql
SELECT id, name, address->>'country' AS country FROM users;
```